1. 脚手架开发自定义模版逻辑
async installCustomlTemplate() {
// 查询自定义模板的入口文件
if (await this.templateNpm.exists()) {
const rootFile = this.templateNpm.getRootFilePath();
if (fs.existsSync(rootFile)) {
log.notice('开始执行自定义模板');
const templatePath = path.resolve(this.templateNpm.cacheFilePath, 'template');
const options = {
templateInfo: this.templateInfo,
projectInfo: this.projectInfo,
sourcePath: templatePath,
targetPath: process.cwd(),
};
// 执行自定义模版中main指向的文件
const code = `require('${rootFile}')(${JSON.stringify(options)})`;
log.verbose('code', code);
await execAsync('node', ['-e', code], { stdio: 'inherit', cwd: process.cwd() });
log.success('自定义模板安装成功');
} else {
throw new Error('自定义模板入口文件不存在!');
}
}
}
2. 自定义项目模板开发
- 发布自定义模版 cli-dev-zy-template-custom-vue2
- mongodb中配置自定义模版数据。
{
"_id" : ObjectId("60dd5af21f683b5c176f0b4e"),
"name" : "vue2自定义模板",
"npmName" : "cli-dev-zy-template-custom-vue2",
"version" : "1.0.0",
"type" : "custom",
"installCommand" : "npm install --registry=https://registry.npm.taobao.org",
"startCommand" : "npm run serve",
"tag" : [
"project"
],
"ignore" : [
"**/public/**"
]
}
2. 自定义模板执行逻辑开发
在自定义模板中添加 index.js 文件,package.json指向这个文件
- index.js
const path = require('path')
const fse = require('fs-extra');
const inquirer = require('inquirer');
const glob = require('glob');
const ejs = require('ejs');
async function ejsRender(options) {
const dir = options.targetPath;
const projectInfo = options.data;
return new Promise((resolve, reject) => {
glob('**', {
cwd: dir,
ignore: options.ignore || '',
nodir: true,
}, function (err, files) {
if (err) {
reject(err);
}
Promise.all(files.map(file => {
const filePath = path.join(dir, file);
return new Promise((resolve1, reject1) => {
ejs.renderFile(filePath, projectInfo, {}, (err, result) => {
if (err) {
reject1(err);
} else {
fse.writeFileSync(filePath, result);
resolve1(result);
}
});
});
})).then(() => {
resolve();
}).catch(err => {
reject(err);
});
});
});
}
async function install(options) {
const projectPrompt = [];
const descriptionPrompt = {
type: 'input',
name: 'description',
message: '请输入项目描述信息',
default: '',
validate: function (v) {
const done = this.async();
setTimeout(function () {
if (!v) {
done('请输入项目描述信息');
return;
}
done(null, true);
}, 0);
},
};
projectPrompt.push(descriptionPrompt);
const projectInfo = await inquirer.prompt(projectPrompt);
options.projectInfo.description = projectInfo.description;
try {
const { sourcePath, targetPath } = options;
fse.ensureDirSync(sourcePath)
fse.ensureDirSync(targetPath)
fse.copySync(sourcePath, targetPath)
// 动态配置ignore
const templateIgnore = options.templateInfo.ignore || []
const ignore = ['**/node_modules/**', ...templateIgnore]
await ejsRender({ ignore, targetPath, data: options.projectInfo })
// const { installCommand, startCommand } = this.templateInfo
// 依赖安装
// await this.execCommand(installCommand, '依赖安装过程中失败!')
// 启动命令执行
// await this.execCommand(startCommand, '执行启动命令失败!')
} catch (e) {
throw e
}
}
module.exports = install
- package.json
{
"name": "cli-dev-zy-template-custom-vue2",
"version": "1.0.2",
"description": "",
"author": "",
"license": "ISC",
"main": "index.js",
"dependencies": {
"ejs": "^3.1.5",
"fs-extra": "^9.0.1",
"glob": "^7.1.6",
"inquirer": "^7.3.3"
}
}